//
//  AppController.m
//  TraceViewer
//
//  Created by Vladimir Sarpe on 23/06/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "AppController.h"

@implementation AppController

- (IBAction)open:(id)sender {
	// File type will be an trace event file (.ev)
	NSArray* fileTypes = [NSArray arrayWithObjects:@"ev", @"procs", nil];
	
	// Set variables for the NSOpenPanel
	NSOpenPanel* openPanel = [NSOpenPanel openPanel];
	[openPanel setAlphaValue:0.95]; // transparancy value
	[openPanel setTitle:@"Select a trace file to open"];
	[openPanel setCanChooseFiles:YES];
	[openPanel setCanChooseDirectories:NO];
	[openPanel setCanCreateDirectories:YES];
	[openPanel setAllowsMultipleSelection:NO];			
	lastevent = @"0";
	int i;
	if([openPanel runModalForDirectory:nil file:nil types:fileTypes] == NSOKButton ) {
		NSArray* files = [openPanel filenames];
		for(i = 0; i < [files count]; i++) {
			NSString* fileName = [files objectAtIndex:i];
			[showAction setStringValue:fileName];
			send = [[NSMutableArray alloc] init];
			die = [[NSMutableArray alloc] init];
			spawn = [[NSMutableArray alloc] init];
			procs = [[NSMutableArray alloc] init];
			NSString* event;
			curr_proc = @"0";
			p_sends = 0;
			p_spawns = 0;
			p_rec = 0;
			[progress startAnimation:sender];
			NSString *fileContent = [[NSString alloc] initWithContentsOfFile:fileName];
			NSCharacterSet* newLine = [NSCharacterSet newlineCharacterSet];
			NSScanner* scanner = [NSScanner scannerWithString:fileContent];
			while (![scanner isAtEnd]) {
				if ([scanner scanUpToCharactersFromSet:newLine intoString:&event]){
					[self breakEvent:event fromFile:fileName];
				}
			}
			NSString* action = [NSString stringWithFormat:@"%@\t: %@ µs", fileName, lastevent];
			/*float succ_sends;
			NSString* succ;
			if (p_sends == 0) {
				succ_sends= 0.0;
				succ = [NSString stringWithFormat:@"n/a"];
			}
			else {
				succ_sends = ((float)p_rec/(float)p_sends) * 100;
				succ = [NSString stringWithFormat:@"%.0f", succ_sends];
			}*/
			NSString* details = [NSString stringWithFormat:@"\nstart: %@\ndies: %@\n\t-sends: %d (%d successful)\n\t-spawns: %d", start, end, p_sends, p_rec, p_spawns];
			[procs addObject:[NSString stringWithFormat:@"**%@**%@", curr_proc, details]];
			[procs removeObjectAtIndex:0];
			[showAction setStringValue:action];
			[dataSource updateData:procs];
			[sideView setDataSource:dataSource];
			[sideView reloadData];
			[bottomView loadSends:send andSpawn:spawn andDie:die andLast:lastevent];
		}
		[progress stopAnimation:sender];
	}
}

- (void)breakEvent:(NSString*) event fromFile:(NSString*) file {
	NSString* raw_event;
	NSString *send_type, *spawn_type, *die_type;
	int ts_pos, die_ts_pos;
	if ([[file substringFromIndex:[file length]-2] isEqualToString:@"ev"]) {
		send_type = @"send";
		spawn_type = @"spawn";
		die_type = @"die";
		ts_pos = 1;
		die_ts_pos = ts_pos;
		raw_event = event;
	}
	else if ([[file substringFromIndex:[file length]-2] isEqualToString:@"cs"]) {
		send_type = @"SEND ";
		spawn_type = @"SPAWN ";
		die_type = @"DIE ";
		ts_pos = 2;
		die_ts_pos = ts_pos - 1;
		raw_event = [@"--||" stringByAppendingString:event];
	}
	NSScanner* scanner;
	NSString* token;
	NSString* details;
	NSMutableArray* brokenEvent = [[NSMutableArray alloc] init];
	scanner = [NSScanner scannerWithString:raw_event];
	while (![scanner isAtEnd]) {
		[scanner setScanLocation: [scanner scanLocation]+2];
		if ([scanner scanUpToString:@"||" intoString:&token]){
			[brokenEvent addObject:token];
		}	
	}
	NSString* type = [brokenEvent objectAtIndex:0];
	NSString* timestamp = @"0";
	if ([type isEqualToString:send_type]){
		p_sends = p_sends + 1;
		if (![[brokenEvent objectAtIndex:3] isEqualToString:@"-1"]) {
			p_rec = p_rec + 1;
		}
		timestamp = [brokenEvent objectAtIndex:ts_pos];
		[send addObject:timestamp];
	}
	else if ([type isEqualToString:spawn_type]) {
		p_spawns = p_spawns + 1;
		timestamp = [brokenEvent objectAtIndex:ts_pos];
		[spawn addObject:timestamp];
	}
	else if ([type isEqualToString:die_type]) {
		end = [brokenEvent objectAtIndex:1];
		//end = @"not implemented"; ///////////////////////////////////////////////////////////////////// !!!!!!
		timestamp = [brokenEvent objectAtIndex:die_ts_pos];
		[die addObject:timestamp];
	}
	else if ([type isEqualToString:@"PROCESS "]) {
		/*float succ_sends;
		NSString* succ;
		if (p_sends == 0) {
			succ_sends= 0.0;
			succ = [NSString stringWithFormat:@"n/a"];

		}
		else {
			succ_sends = ((float)p_rec / (float)p_sends) * 100;		
			succ = [NSString stringWithFormat:@"%.0f%", succ_sends];
		}*/
		if ([end isEqualToString:@"-1"]) {
			end = @"n/a";
		}
		start = [brokenEvent objectAtIndex:2];
		if ([start isEqualToString:@"0"]) {
			start = @"n/a";
		}
		details = [NSString stringWithFormat:@"\nstart: %@\ndies: %@\n\t-sends: %d (%d successful)\n\t-spawns: %d", start, end, p_sends, p_rec, p_spawns];
		[procs addObject:[NSString stringWithFormat:@"**%@**%@", curr_proc, details]];
		end = @"-1";
		curr_proc = [brokenEvent objectAtIndex:1];
		p_sends = 0;
		p_spawns = 0;
		p_rec = 0;
	}
	if ([timestamp intValue] > [lastevent intValue]) {
		lastevent = timestamp;
	}
}

- (IBAction)zoom:(id)sender {
	[bottomView notifyZoom:([slider floatValue])];
}

- (IBAction)search:(id)sender {
	
}

@end
